﻿using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;
using Cms.Domain.Wrappers;
using Cms.Utilities;
using Cms.Web.Framework.Plugins.Attributes;
using Cms.Web.Framework.Plugins.Helpers;
using iLib.Web.UI.WebControls;

namespace Cms.Web.Framework.Plugins
{
    public class SearchResult : BaseTemplatedPlugin
    {
        // Property fields
        private int _defaultPageSize;
        private int _categoryID;

        // Internal fields
        private string _searchQuery;

        // Template controls
        private Literal litQuery;
        private iPagedNavigation lowerPages;
        private Panel pnlLower;
        private Panel pnlNoHits;
        private Panel pnlUpper;
        private Repeater rpPagedNavigationTemplateWrapper;
        private Repeater rpResult;
        private iPagedNavigation upperPages;
        
        public int DefaultPageSize
        {
            get { return _defaultPageSize; }
            set { _defaultPageSize = value; }
        }

        [Enumeration("Categories", false)]
        public int CategoryID
        {
            get { return _categoryID; }
            set { _categoryID = value; }
        }

        private string FilterState
        {
            get { return ViewState["FilterState"] == null ? string.Empty : ViewState["FilterState"].ToString(); }
            set { ViewState["FilterState"] = value; }
        }

        protected override void CreateChildControls()
        {
            try
            {
                base.CreateChildControls();

                // Find controls
                litQuery = (Literal)FindControl("litQuery");
                pnlUpper = (Panel)FindControl("pnlUpper");
                pnlLower = (Panel)FindControl("pnlLower");
                upperPages = (iPagedNavigation)FindControl("upperPages");
                lowerPages = (iPagedNavigation)FindControl("lowerPages");
                rpPagedNavigationTemplateWrapper = (Repeater)FindControl("rpPagedNavigationTemplateWrapper");
                rpResult = (Repeater)FindControl("rpResult");
                pnlNoHits = (Panel)FindControl("pnlNoHits");

                // Bind events
                upperPages.Click += PagedNavigation_Click;
                upperPages.Ready += PagedNavigation_Ready;
                lowerPages.Click += PagedNavigation_Click;
                lowerPages.Ready += PagedNavigation_Ready;
                rpResult.ItemDataBound += rpResult_ItemDataBound;

                // Setup the PagedNavigationTemplates
                int[] t = { 1, 2 };
                rpPagedNavigationTemplateWrapper.EnableViewState = false;
                rpPagedNavigationTemplateWrapper.DataSource = t;
                rpPagedNavigationTemplateWrapper.DataBind();
                upperPages.TemplateContainerControl = rpPagedNavigationTemplateWrapper.Items[0].FindControl("pnlPagedNavigationTemplate");
                lowerPages.TemplateContainerControl = rpPagedNavigationTemplateWrapper.Items[1].FindControl("pnlPagedNavigationTemplate");
                rpPagedNavigationTemplateWrapper.Visible = false;

                // Initialize
                if (Page.IsPostBack)
                    return;
                upperPages.PageSize = _defaultPageSize;
                lowerPages.PageSize = _defaultPageSize;
                SetResult(0, true);
            }
            catch (Exception ex)
            {
                Logging.LogError("SearchResult", ex);
                Controls.Clear();
            }
        }
        
        private void SetResult(int currentPage, bool rebuildFilter)
        {
            var filter = new SearchContentFilter(FilterState)
                             {
                                 CurrentPage = currentPage,
                                 Freetext = RequestDetails.GetQueryStringValue("q")
                             };
            _searchQuery = Html.Encode(filter.Freetext).Trim();
            if (rebuildFilter)
            {
                filter.PageSize = _defaultPageSize; // This should somehow get the page size from the GUI
            }

            IPageRepository pageRepository = new PageRepository();
            IList<SearchResultHit> result = pageRepository.Search(ref filter, RequestDetails.Locale.ID, _categoryID, RequestDetails.User);
            FilterState = filter.GetQuery();

            pnlUpper.Visible = true;
            upperPages.PageSize = filter.PageSize;
            upperPages.CurrentPage = filter.CurrentPage;
            upperPages.ItemCount = filter.Count;
            pnlLower.Visible = pnlUpper.Visible;
            lowerPages.PageSize = upperPages.PageSize;
            lowerPages.CurrentPage = upperPages.CurrentPage;
            lowerPages.ItemCount = upperPages.ItemCount;
            rpResult.DataSource = result;
            rpResult.DataBind();
            pnlNoHits.Visible = rpResult.Items.Count == 0;
            if (litQuery != null)
            {
                litQuery.Text = _searchQuery;
            }
        }

        private void rpResult_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem)
                return;
            var hit = (SearchResultHit)e.Item.DataItem;
            var hlPage = (HyperLink)e.Item.FindControl("hlPage");
            var litTitle = (Literal)e.Item.FindControl("litTitle");
            var litUrl = (Literal)e.Item.FindControl("litUrl");
            var pnlContent = (Panel)e.Item.FindControl("pnlContent");
            hlPage.NavigateUrl = "~/";
            if (RequestDetails.Locale != RequestDetails.Site.DefaultLocale)
            {
                hlPage.NavigateUrl += RequestDetails.Locale.UrlCode + "/";
            }
            hlPage.NavigateUrl += hit.Url;
            if (litUrl != null)
            {
                litUrl.Text = hlPage.NavigateUrl.Substring(2);
            }
            if (litTitle != null)
            {
                litTitle.Text = hit.Title;
            }

            // Parse the html returned to make sure that the output of fredium plugins are included
            // Use the panel as placeholder for the resulting control tree
            ContentParser.Parse(hit.Html, pnlContent, RequestDetails.RequestedUrl);

            // Get the resulting html from the panel control
            string html = Misc.RenderControlHtml(pnlContent);

            html = SearchResultHelper.ExtractFirstOccurenceOfSearchQueryFromHtmlWithPadding(html, _searchQuery);

            // Clear the panel and insert the extracted hit instead
            pnlContent.Controls.Clear();
            pnlContent.Controls.Add(new LiteralControl(html));

            // Make sure any custom OnItemDataBound logic gets executed
            ((SearchResult)TemplateInstance).OnItemDataBound(sender, e);
        }

        public virtual void OnItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            // This can be overridden in the template
        }

        private void PagedNavigation_Click(int currentPage)
        {
            SetResult(currentPage, false);
        }
        
        private void PagedNavigation_Ready(bool visible)
        {
            pnlUpper.Visible = visible;
            pnlLower.Visible = pnlUpper.Visible;
        }
    }
}